import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { getRoles, getRoleOptions, type Role, type RoleOption } from '@/api/roles'
import { useUserStore } from '@/stores/user'
import { getUserRoleCodes } from '@/api/users'

export interface RoleDictionaryItem extends Role {
  code: string
}

export const useRoleStore = defineStore('role', () => {
  const roles = ref<RoleDictionaryItem[]>([])
  const loading = ref(false)
  const initialized = ref(false)
  const lastFetchedAt = ref<number | null>(null)

  const roleMap = computed<Record<string, RoleDictionaryItem>>(() => {
    const map: Record<string, RoleDictionaryItem> = {}
    roles.value.forEach(role => {
      const code = role.code || role.id
      if (code) {
        map[code] = role
      }
    })
    return map
  })

  const generateTempId = () => `role_${Math.random().toString(36).slice(2, 10)}`

  const normalizeRoles = (rawRoles: Partial<Role>[]): RoleDictionaryItem[] => {
    return rawRoles
      .filter(role => !!role)
      .map((role) => ({
        id: role.id || role.code || generateTempId(),
        name: role.name || role.code || '未命名角色',
        code: role.code || role.id || generateTempId(),
        description: role.description || '',
        permissions: Array.isArray(role.permissions) ? role.permissions : [],
        is_system: Boolean(role.is_system),
        is_active: role.is_active !== false,
        created_at: role.created_at,
        updated_at: role.updated_at
      }))
  }

  const fallbackRoleLabelMap: Record<string, string> = {
    admin: '管理员',
    project_manager: '项目经理',
    product_manager: '产品经理',
    operations_specialist: '运营专员',
    ops_engineer: '运维工程师',
    developer: '开发者',
    tester: '测试人员',
    viewer: '查看者',
    user: '普通用户'
  }

  const buildFallbackFromOptions = (options: RoleOption[]): RoleDictionaryItem[] => {
    return options.map((option) => ({
      id: option.value,
      name: option.label,
      code: option.value,
      description: option.description || '',
      permissions: [],
      is_system: false,
      is_active: true,
      created_at: undefined,
      updated_at: undefined
    }))
  }

  const buildFallbackFromCodes = (codes: string[]): RoleDictionaryItem[] => {
    const uniqueCodes = Array.from(
      new Set(
        codes
          .filter(code => typeof code === 'string')
          .map(code => code.trim())
          .filter(code => code.length > 0)
      )
    )

    return uniqueCodes.map((normalizedCode) => ({
      id: normalizedCode,
      name: fallbackRoleLabelMap[normalizedCode] || normalizedCode,
      code: normalizedCode,
      description: fallbackRoleLabelMap[normalizedCode] ? `${fallbackRoleLabelMap[normalizedCode]}（系统角色）` : '',
      permissions: [],
      is_system: true,
      is_active: true,
      created_at: undefined,
      updated_at: undefined
    }))
  }

  const applyRoles = (items: RoleDictionaryItem[]) => {
    if (!items || items.length === 0) return false
    roles.value = items
    initialized.value = true
    lastFetchedAt.value = Date.now()
    return true
  }

  const CACHE_DURATION = 5 * 60 * 1000

  const resetRoles = () => {
    roles.value = []
    initialized.value = false
    lastFetchedAt.value = null
  }

  const hasFreshRoles = () => {
    return (
      roles.value.length > 0 &&
      lastFetchedAt.value !== null &&
      Date.now() - lastFetchedAt.value < CACHE_DURATION
    )
  }

  const tryApplyFallbackOptions = async () => {
    const fallbackOptions = await getRoleOptions()
    if (applyRoles(buildFallbackFromOptions(fallbackOptions))) {
      return roles.value
    }

    const roleCodes = await getUserRoleCodes()
    if (applyRoles(buildFallbackFromCodes(roleCodes))) {
      return roles.value
    }

    console.warn('公开角色选项接口返回空数据', {
      fallbackOptions,
      roleCodes
    })
    resetRoles()
    throw new Error('未获取到任何角色数据')
  }

  const fetchRoles = async (force = false): Promise<RoleDictionaryItem[]> => {
    if (loading.value) return roles.value
    if (!force && hasFreshRoles()) {
      return roles.value
    }

    // 检查用户是否有权限访问角色列表接口
    const userStore = useUserStore()
    const hasRoleViewPermission = userStore.hasPermission('role:view')
    
    // 如果没有权限，直接使用备用方案，不调用接口
    if (!hasRoleViewPermission) {
      console.warn('当前用户无权限访问角色列表接口，直接使用备用方案')
      try {
        return await tryApplyFallbackOptions()
      } catch (fallbackError) {
        console.warn('获取角色字典备用数据失败:', fallbackError)
        resetRoles()
        return roles.value
      }
    }

    loading.value = true
    try {
      const data = await getRoles()
      const normalized = normalizeRoles(Array.isArray(data) ? data : [])
      
      if (applyRoles(normalized)) {
        return roles.value
      }

      console.warn('角色接口返回空数据，将尝试公开选项接口', data)
      return await tryApplyFallbackOptions()
    } catch (error: any) {
      // 如果是权限错误，静默处理，尝试使用备用方案
      const isPermissionError = error && typeof error === 'object' && 
        ('isPermissionError' in error ? error.isPermissionError() : 
         error.type === 'PERMISSION_ERROR' || error.type === 'AUTHENTICATION_ERROR' ||
         error.response?.status === 403)
      
      if (isPermissionError) {
        console.warn('当前用户无权限访问角色列表，尝试使用备用方案')
      } else {
        console.error('获取角色字典失败:', error)
      }
      
      try {
        return await tryApplyFallbackOptions()
      } catch (fallbackError) {
        // 如果备用方案也失败，且不是权限错误，才抛出错误
        if (!isPermissionError) {
          console.error('获取角色字典备用数据失败:', fallbackError)
        }
        resetRoles()
        // 对于权限错误，不抛出异常，返回空数组，让页面正常显示
        if (isPermissionError) {
          return roles.value
        }
        throw (fallbackError instanceof Error ? fallbackError : new Error('获取角色列表失败'))
      }
    } finally {
      loading.value = false
    }
  }

  const getRoleName = (code: string | undefined | null): string => {
    if (!code) return ''
    return roleMap.value[code]?.name || code
  }

  const getRoleDescription = (code: string | undefined | null): string => {
    if (!code) return ''
    return roleMap.value[code]?.description || ''
  }

  const getRoleTagType = (code: string | undefined | null): 'primary' | 'success' | 'warning' | 'danger' | 'info' => {
    if (!code) return 'info'
    const value = code.toLowerCase()
    if (value.includes('admin')) return 'danger'
    if (value.includes('manager') || value.includes('product')) return 'warning'
    if (value.includes('operation') || value.includes('ops')) return 'success'
    if (value.includes('developer') || value.includes('dev')) return 'primary'
    if (value.includes('test')) return 'success'
    if (value.includes('viewer') || value.includes('user') || value.includes('guest')) return 'info'
    return 'info'
  }

  const roleOptions = computed(() =>
    roles.value.map(role => ({
      label: role.name,
      value: role.code,
      description: role.description
    }))
  )

  return {
    roles,
    roleMap,
    loading,
    initialized,
    fetchRoles,
    getRoleName,
    getRoleDescription,
    getRoleTagType,
    roleOptions
  }
})

